package agent;

import java.awt.Color;
import java.awt.Graphics2D;
import java.util.ArrayList;

import obstacle.IObstacle;

import Vue.CAImageBuffer;
import Vue.Terrain;
import reseau.*;

public class Agent implements IObstacle
{
	protected Coordonnees2D position;
	protected Coordonnees2D objectif;
	
	protected Vecteur2D vecteurDeplacement;
	protected double vitesseDeplacement = 10;
	
	protected WayPoint wayPointCourant;
	protected ArrayList<WayPoint> cheminASuivre;
	
	protected Terrain terrain;
	
	protected int rayon;
	protected int rayon_carre;
	
	protected int 	_redValue;
	protected int 	_greenValue;
	protected int 	_blueValue;
	
	protected Coordonnees2D positionAncienne;
	
	public Agent(Terrain terrain, Coordonnees2D position, int rayon)
	{
		this.terrain = terrain;
		this.vecteurDeplacement = new Vecteur2D(0, 0);
		this.position = position;
		this.objectif = new Coordonnees2D(position);
		this.positionAncienne = new Coordonnees2D(position);
		this.wayPointCourant = this.terrain.get_reseau().getWayPointProche(this.position);
		this.cheminASuivre = new ArrayList<WayPoint>();
		
		this.rayon = rayon;
		this.rayon_carre = this.rayon*this.rayon;
	}
	protected void setColot(int r, int g, int b)
	{
		this._redValue = r;
		this._greenValue =g;
		this._blueValue =b;
	}
	public Coordonnees2D getIntersection(Coordonnees2D origine, Coordonnees2D destination)
	{
		Coordonnees2D intersection = null;
		
		double dx = destination.getY()-origine.getY();
		double dy = destination.getX()-origine.getX();
		double Ox = origine.getX() - this.position.getX();
		double Oy = origine.getY() - this.position.getY();
		
		double a = dx*dx + dy*dy;
		double b = 2*(dx*Ox + dy*Oy);
		double c = Ox*Ox + Oy*Oy - this.rayon_carre;
		
		double delta = b*b - 4*a*c;
		
		if(delta>=0)
		{
			double racine_delta = Math.sqrt(delta);
			double t = (-b-racine_delta)/2*a;
			double x = (origine.getX() + t*dx);
			double y = (origine.getY() + t*dy);
			intersection = new Coordonnees2D(x, y);
		}
		
		return intersection;
	}
	
	public Vecteur2D getVecteurTangent(Coordonnees2D origine, Coordonnees2D destination)
	{
		Vecteur2D vecteurTangent = null;
		Coordonnees2D intersection = this.getIntersection(origine, destination);
		
		if(intersection!=null)
		{
			Vecteur2D vecteurCentre = new Vecteur2D(this.position, intersection);
			if(vecteurCentre.getY()!=0)
				vecteurTangent = new Vecteur2D(1, vecteurCentre.getX()/vecteurCentre.getY());
			else if(vecteurCentre.getX()!=0)
				vecteurTangent = new Vecteur2D(0, 1);
			else
				vecteurTangent = new Vecteur2D(0, 0);
		}
		
		return vecteurTangent;
	}
	
	protected void deplacer()
	{ 
		this.position.add(this.vecteurDeplacement);
		this.atteindreWayPoint();
		this.atteindreObjectif();
	}
	
	private void atteindreWayPoint()
	{
		// si il nous reste du chemin a parcourir
		if(!this.cheminASuivre.isEmpty())
			// et si on approche a une certaine distance du waypoint � atteindre
			if(this.position.distanceA(this.cheminASuivre.get(0).getPosition())<this.rayon)
				// on d�pile le waypoint a atteindre du chemin a suivre et on le met dans le waypointcourant
				this.wayPointCourant = this.cheminASuivre.remove(0);
	}
	
	private void atteindreObjectif()
	{
		if(this.position.distanceA(this.objectif)<this.rayon)
			this.objectif.copy(this.position);
	}
	
	protected void deciderObjectif()
	{}
	
	public void avancer()
	{
		this.deciderObjectif();
		
		this.positionAncienne.copy(position);
		// si on ne se trouve pas encore � son objectif
		if(!this.position.equals(this.objectif))
		{
			Coordonnees2D destination;
			
			// mais que l'on est arriv� au dernier waypoint
			if(this.cheminASuivre.isEmpty())
				destination = this.objectif;
			// si on est encore sur le chemin
			else
				destination = this.cheminASuivre.get(0).getPosition();
			
			this.vecteurDeplacement.set(this.position, destination);
			this.vecteurDeplacement.normaliser(this.vitesseDeplacement);
			
			Coordonnees2D destinationImmediate = new Coordonnees2D(this.position);
			destinationImmediate.add(this.vecteurDeplacement);
			
			Vecteur2D vecteurTangent;
			for(IObstacle obstacle : this.terrain.get_lstObstacles())
				if((vecteurTangent=obstacle.getVecteurTangent(this.position, destinationImmediate))!=null)
				{
					System.out.println("touche");
					if(this.vecteurDeplacement.scalaire(vecteurTangent)<0)
					{
						System.out.println("inversion");
						vecteurTangent.fois(-1);
					}
					else
					{
						System.out.println("xxxxxx");
					}
					this.vecteurDeplacement.copy(vecteurTangent);
					break;
				}
			
			for(Agent agent : this.terrain.get_agents())
				if((agent!=this)  && (vecteurTangent=agent.getVecteurTangent(this.position, destinationImmediate))!=null)
				{
					this.vecteurDeplacement.copy(vecteurTangent);
					break;
				}
			
			this.vecteurDeplacement.normaliser(this.vitesseDeplacement);
			this.deplacer();
		}
	}
	
//	public void display(CAImageBuffer image)
//	{
//		
//		
//	}
//	
	public void setObjectif(Coordonnees2D obj)
	{
		this.objectif = obj;
		this.cheminASuivre = this.terrain.get_astar().getChemin(this.position, obj);
	}
	@Override
	public void display(Graphics2D g) {
		// TODO Auto-generated method stub
		for(int i=0; i<this.rayon; i++)
		{
			for(int j=0; j<this.rayon; j++)
			{
				this.terrain.setCellState((int)this.positionAncienne.getX()-i,(int)this.positionAncienne.getY()-j, 255, 255, 255);
				this.terrain.setCellState((int)this.position.getX()-i,(int)this.position.getY()-j, this._redValue, this._greenValue, this._blueValue);
			}
		}
		g.setColor(new Color(37,170,30));
		//this.terrain.setCellState((int)this.position.getX(),(int)this.position.getY(), 37, 170, 30);
		//g.fillOval((int)this.position.getX() - this.rayon, (int)this.position.getY() - this.rayon, this.rayon, this.rayon);
		
		if(!this.cheminASuivre.isEmpty())
		{
			g.setColor(new Color(250,0,0));
			g.fillOval((int)this.cheminASuivre.get(0).getPosition().getX(), (int)this.cheminASuivre.get(0).getPosition().getY(), this.rayon, this.rayon);
		}
		//g.setColor(new Color(255,0,0));
		//this.terrain.setCellState((int)this.objectif.getX(),(int)this.objectif.getY(),255,0,0);
		//g.fillOval((int)this.objectif.getX() - this.rayon, (int)this.objectif.getY() - this.rayon, this.rayon, this.rayon);
	}
	@Override
	public boolean contient(Coordonnees2D point) {
		// TODO Auto-generated method stub
		return false;
	}
	@Override
	public boolean tue() {
		// TODO Auto-generated method stub
		return false;
	}
	public Coordonnees2D getPosition()
	{
		return this.position;
	}
}
